<?php

namespace SunAdmin\Service\Ws;

use SunAdmin\Model\AccountModel;
use SunAdmin\Service\AccountService;
use Swoole\WebSocket\Frame;
use think\swoole\Websocket;
use think\facade\Log;

class WsHandle extends BaseWebSocketService
{
    private FdUidBinding $fdUidBinding;
    private SendMessage $sendMessage;
    private ReceiveMessage $receiveMessage;

    public function __construct(string $connectionType)
    {
        parent::__construct($connectionType);

        $this->fdUidBinding = new FdUidBinding($connectionType);
        $this->sendMessage = new SendMessage($connectionType);
        $this->receiveMessage = new ReceiveMessage($connectionType);
    }

    /**
     * 处理WebSocket连接打开
     */
    public function onOpen(Websocket $websocket, $request): void
    {
        $fd = $websocket->getSender();

        try {
            // 获取用户ID，根据连接类型使用不同的参数名
            $uid = $this->getUserIdFromRequest($request);

            if (!$uid) {
                Log::warning("[webSocket] WebSocket连接失败：缺少用户ID | " . json_encode([
                        'type' => $this->connectionType,
                        'fd' => $fd
                    ]));
                $websocket->close();
                return;
            }

            // 绑定fd与uid
            $this->fdUidBinding->bind($fd, $uid);

            // 更新用户在线状态
            $this->updateUserOnlineStatus($uid, 1);

            // 广播用户上线状态（仅admin类型）
            if ($this->connectionType === 'admin') {
                AccountService::sendAllAdminOnlineStatus($fd, 1);
            }

            Log::info("[webSocket] WebSocket连接成功 | " . json_encode([
                    'type' => $this->connectionType,
                    'fd' => $fd,
                    'uid' => $uid
                ]));

        } catch (\Throwable $e) {
            Log::error("[webSocket] WebSocket连接处理异常 | " . json_encode([
                    'type' => $this->connectionType,
                    'fd' => $fd,
                    'error' => $e->getMessage()
                ]));
            $websocket->close();
        }
    }

    /**
     * 处理WebSocket消息
     */
    public function onMessage(Websocket $websocket, Frame $frame): void
    {
        $fd = $websocket->getSender();

        try {
            // 直接将原始消息数据传递给ReceiveMessage处理
            $this->receiveMessage->handle($fd, $frame->data, $websocket);

        } catch (\Throwable $e) {
            Log::error("[webSocket] WebSocket消息处理异常 | " . json_encode([
                    'type' => $this->connectionType,
                    'fd' => $fd,
                    'error' => $e->getMessage(),
                    'data' => $frame->data ?? 'unknown'
                ]));
        }
    }

    /**
     * 处理WebSocket连接关闭
     */
    public function onClose(Websocket $websocket): void
    {
        $fd = $websocket->getSender();

        try {
            // 通过fd获取uid
            $uid = $this->fdUidBinding->fdToUid($fd);

            if ($uid) {
                // 更新用户离线状态
                $this->updateUserOnlineStatus($uid, 0);

                // 广播用户下线状态（仅admin类型）
                if ($this->connectionType === 'admin') {
                    AccountService::sendAllAdminOnlineStatus($fd, 0);
                }

                Log::info("[webSocket] WebSocket连接断开 | " . json_encode([
                        'type' => $this->connectionType,
                        'fd' => $fd,
                        'uid' => $uid
                    ]));
            }

            // 解绑fd
            $this->fdUidBinding->unbind($fd);

        } catch (\Throwable $e) {
            Log::error("[webSocket] WebSocket关闭处理异常 | " . json_encode([
                    'type' => $this->connectionType,
                    'fd' => $fd,
                    'error' => $e->getMessage(),
                    'trace' => $e->getTraceAsString()
                ]));
        }
    }

    /**
     * 从请求中获取用户ID
     */
    private function getUserIdFromRequest($request): ?int
    {
        switch ($this->connectionType) {
            case 'admin':
                return $request->adminUid ?? null;
            case 'client':
                return $request->clientUid ?? null;
            default:
                return null;
        }
    }

    /**
     * 更新用户在线状态
     */
    private function updateUserOnlineStatus(int $uid, int $status): void
    {
        try {
            if ($this->connectionType === 'admin') {
                // 更新admin在线状态
                AccountModel::update(['online_status' => $status], ['id' => $uid]);
            } else {
                // 客户端用户状态更新逻辑
                Log::info("[webSocket] 客户端用户状态更新 | " . json_encode([
                        'uid' => $uid,
                        'status' => $status
                    ]));
            }
        } catch (\Throwable $e) {
            Log::error("[webSocket] 更新用户在线状态失败 | " . json_encode([
                    'type' => $this->connectionType,
                    'uid' => $uid,
                    'status' => $status,
                    'error' => $e->getMessage()
                ]));
        }
    }
} 